﻿using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Web;
using Microsoft.Practices.EnterpriseLibrary.Data;
using System.Data;

namespace DMS.Base
{
    public class LogManager: Helper
    {
        #region 异常处理

        #region SQL查询句子
        private const string SQL_SYS_ErrorLog = @"SELECT {0} [ErrorID]
                                                      ,[P_ErrorID]
                                                      ,[ErrorType]
                                                      ,[HResult]
                                                      ,[Message]
                                                      ,[Source]
                                                      ,[StackTrace]
                                                      ,[TargetSite]
                                                      ,[CurrentUser]
                                                      ,[CurrentUserID]
                                                      ,[RequestURL]
                                                      ,[ClinetIP]
                                                      ,[ClientBroswer]
                                                      ,[CreateTime]
                                                  FROM [dbo].[SYS_ErrorLogs]";
        private const string SQL_SYS_ErrorLog_Count = @"SELECT COUNT(*) AS Total
                                                    FROM [dbo].[SYS_ErrorLogs]";
        private const string SQL_SYS_ErrorLog_Order = @"ORDER BY [CreateTime] DESC";
        private const string SQL_SYS_ErrorLog_Add = @"INSERT INTO [dbo].[SYS_ErrorLogs]
                                                                   ([ErrorID]
                                                                   ,[P_ErrorID]
                                                                   ,[ErrorType]
                                                                   --,[HResult]
                                                                   ,[Message]
                                                                   ,[Source]
                                                                   ,[StackTrace]
                                                                   ,[TargetSite]
                                                                   ,[CurrentUser]
                                                                   ,[CurrentUserID]
                                                                   ,[RequestURL]
                                                                   ,[ClinetIP]
                                                                   ,[ClientBroswer])
                                                             VALUES
                                                                   (@ErrorID
                                                                   ,@P_ErrorID
                                                                   ,@ErrorType
                                                                   --,@HResult
                                                                   ,@Message
                                                                   ,@Source
                                                                   ,@StackTrace
                                                                   ,@TargetSite
                                                                   ,@CurrentUser
                                                                   ,@CurrentUserID
                                                                   ,@RequestURL
                                                                   ,@ClinetIP
                                                                   ,@ClientBroswer)";
        #endregion

        /// <summary>
        /// 记录异常
        /// </summary>
        /// <param name="operatorID">操作人ID</param>
        /// <param name="operatorName">操作人名称</param>
        /// <param name="ex">异常</param>
        /// <param name="msg">错误信息</param>
        /// <returns></returns>
        public static string LogException(string operatorID, string operatorName, Exception ex, string msg)
        {
            string code = CreateLogCode();
            SaveLog(operatorID,operatorName, ex, msg, code);

            if (ex != null)
            {
                code += string.Format("\\r\\n错误信息：{0}", ex.Message);
            }

            return code;
        }
        /// <summary>
        /// 获取异常列表
        /// </summary>
        /// <param name="limite"></param>
        /// <param name="page"></param>
        /// <param name="total"></param>
        /// <param name="condition"></param>
        /// <param name="dbParams"></param>
        /// <returns></returns>
        public static DataSet GetLogs(int limite, int page, out int total, string condition, List<DbParameter> dbParams)
        {
            total = 0;
            Database db = DBHelper.Instance;
            string topClause = string.Empty;
            string whereClause = string.Format("WHERE 1 = 1 {0}", condition);
            string countSql = string.Format("{0} {1}", SQL_SYS_ErrorLog_Count, whereClause);
            if (limite > 0)
            {
                topClause = string.Format("Top {0}", limite.ToString());

                if (page > 1)
                {
                    int pageCount = (page - 1) * limite;
                    string subClause = string.Format(@"SELECT TOP {0} [ErrorID]
                                                       FROM [dbo].[SYS_ErrorLogs] {1} {2}", pageCount.ToString(), whereClause, SQL_SYS_ErrorLog_Order);
                    whereClause += string.Format("AND [ErrorID] NOT IN({0})", subClause);
                }
            }
            string mainClause = string.Format(SQL_SYS_ErrorLog, topClause);
            string sql = string.Format("{0} {1} {2}", mainClause, whereClause, SQL_SYS_ErrorLog_Order);
            DbCommand command = db.GetSqlStringCommand(sql);
            if (dbParams != null)
            {
                command.Parameters.AddRange(dbParams.ToArray());
            }

            DataSet ds = db.ExecuteDataSet(command);
            total = GetRecordCount(countSql, dbParams);

            return ds;
        }

        /// <summary>
        /// 生成异常查询号
        /// </summary>
        /// <returns></returns>
        private static string CreateLogCode()
        {
            Random rnd = new Random();
            string nowStr = DateTime.Now.ToString("yyMMdd-hhmmss");

            return string.Format("ER-{0}-{1}", nowStr, rnd.Next(10, 99).ToString());
        }
        /// <summary>
        /// 合成异常信息
        /// </summary>
        /// <param name="ex"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        private static string GetLoDMSg(Exception ex, string msg)
        {
            return string.Format("{0},{1}", msg, (ex == null ? string.Empty : ex.Message));
        }
        /// <summary>
        /// 保存异常信息
        /// </summary>
        /// <param name="ex"></param>
        /// <param name="msg"></param>
        /// <param name="code"></param>
        private static void SaveLog(string operatorID, string operatorName, Exception ex, string msg, string code)
        {
            Database db = DBHelper.Instance;
            DbCommand cmd = db.GetSqlStringCommand(SQL_SYS_ErrorLog_Add);

            #region 造成参数
            DbParameter p_P_ErrorID = cmd.CreateParameter();
            p_P_ErrorID.ParameterName = "P_ErrorID";
            p_P_ErrorID.Value = msg == "#内层错误#" ? code : string.Empty;
            cmd.Parameters.Add(p_P_ErrorID);

            if (msg == "#内层错误#")
            {
                code = Guid.NewGuid().ToString();
            }
            DbParameter p_ErrorID = cmd.CreateParameter();
            p_ErrorID.ParameterName = "ErrorID";
            p_ErrorID.Value = string.IsNullOrEmpty(code) ? Guid.NewGuid().ToString() : code;
            cmd.Parameters.Add(p_ErrorID);

            DbParameter p_ErrorType = cmd.CreateParameter();
            p_ErrorType.ParameterName = "ErrorType";
            p_ErrorType.Value = "1";
            cmd.Parameters.Add(p_ErrorType);

            //DbParameter p_HResult = cmd.CreateParameter();
            //p_HResult.ParameterName = "HResult";
            //p_HResult.Value = ex == null ? string.Empty : ex.HelpLink;
            //cmd.Parameters.Add(p_HResult);

            DbParameter p_Message = cmd.CreateParameter();
            p_Message.ParameterName = "Message";
            p_Message.Value = GetLoDMSg(ex, msg);
            cmd.Parameters.Add(p_Message);

            DbParameter p_Source = cmd.CreateParameter();
            p_Source.ParameterName = "Source";
            p_Source.Value = ex == null ? string.Empty : (ex.Source != null ? ex.Source : "");
            cmd.Parameters.Add(p_Source);

            DbParameter p_StackTrace = cmd.CreateParameter();
            p_StackTrace.ParameterName = "StackTrace";
            p_StackTrace.Value = ex == null ? string.Empty : (ex.StackTrace != null ? ex.StackTrace : "");
            cmd.Parameters.Add(p_StackTrace);

            DbParameter p_TargetSite = cmd.CreateParameter();
            p_TargetSite.ParameterName = "TargetSite";
            p_TargetSite.Value = ex == null ? string.Empty : (ex.TargetSite != null ? ex.TargetSite.Name : "");
            cmd.Parameters.Add(p_TargetSite);

            DbParameter p_CurrentUser = cmd.CreateParameter();
            p_CurrentUser.ParameterName = "CurrentUser";
            p_CurrentUser.Value = operatorName;
            cmd.Parameters.Add(p_CurrentUser);

            DbParameter p_CurrentUserID = cmd.CreateParameter();
            p_CurrentUserID.ParameterName = "CurrentUserID";
            p_CurrentUserID.Value = operatorID;
            cmd.Parameters.Add(p_CurrentUserID);

            HttpContext context = HttpContext.Current;
            DbParameter p_RequestURL = cmd.CreateParameter();
            p_RequestURL.ParameterName = "RequestURL";
            p_RequestURL.Value = context == null ? string.Empty : context.Request.Url.ToString();
            cmd.Parameters.Add(p_RequestURL);

            DbParameter p_ClinetIP = cmd.CreateParameter();
            p_ClinetIP.ParameterName = "ClinetIP";
            p_ClinetIP.Value = context == null ? string.Empty : context.Request.UserHostAddress;
            cmd.Parameters.Add(p_ClinetIP);

            DbParameter p_ClientBroswer = cmd.CreateParameter();
            p_ClientBroswer.ParameterName = "ClientBroswer";
            p_ClientBroswer.Value = context == null ? string.Empty : context.Request.Browser.Type;
            cmd.Parameters.Add(p_ClientBroswer);

            #endregion

            try
            {
                db.ExecuteNonQuery(cmd);
            }
            catch
            {
            }

            if (ex != null && ex.InnerException != null)
            {
                //SaveLog(operatorID, operatorName, ex.InnerException, "#内层错误#", code);
            }
        }
        #endregion

        #region 用户操作记录

        #region SQL查询句子
        private const string SQL_SYS_ActionLog = @"SELECT {0} [OperationID]
                                                          ,[OperationCode]
                                                          ,[OperationContent]
                                                          ,[Operator]
                                                          ,[OperatorID]
                                                          ,[OperateTime]
                                                      FROM [dbo].[SYS_OperationLogs]";
        private const string SQL_SYS_ActionLog_Count = @"SELECT COUNT(*) AS Total
                                                    FROM [dbo].[SYS_OperationLogs]";
        private const string SQL_SYS_ActionLog_Order = @"ORDER BY [OperateTime] DESC";
        private const string SQL_SYS_ActionLog_Add = @"INSERT INTO [dbo].[SYS_OperationLogs]
                                                                   ([OperationID]
                                                                   ,[OperationCode]
                                                                   ,[OperationContent]
                                                                   ,[Operator]
                                                                   ,[OperatorID])
                                                             VALUES
                                                                   (@OperationID
                                                                   ,@OperationCode
                                                                   ,@OperationContent
                                                                   ,@Operator
                                                                   ,@OperatorID)";
        private const string SQL_SYS_ActionLog_OperateCode = @"SELECT DISTINCT [OperationCode]
                                                                FROM [dbo].[SYS_OperationLogs] 
                                                                ORDER BY [OperationCode]";
        #endregion

        /// <summary>
        /// 获取操作类型
        /// </summary>
        /// <returns></returns>
        public static DataSet GetActionCode()
        {
            Database db = DBHelper.Instance;
            DbCommand cmd = db.GetSqlStringCommand(SQL_SYS_ActionLog_OperateCode);

            DataSet ds = db.ExecuteDataSet(cmd);
            return ds;
        }
        /// <summary>
        /// 获取操作列表
        /// </summary>
        /// <param name="limite"></param>
        /// <param name="page"></param>
        /// <param name="total"></param>
        /// <param name="condition"></param>
        /// <param name="dbParams"></param>
        /// <returns></returns>
        public static DataSet GetActions(int limite, int page, out int total, string condition, List<DbParameter> dbParams)
        {
            total = 0;
            Database db = DBHelper.Instance;
            string topClause = string.Empty;
            string whereClause = string.Format("WHERE 1 = 1 {0}", condition);
            string countSql = string.Format("{0} {1}", SQL_SYS_ActionLog_Count, whereClause);
            if (limite > 0)
            {
                topClause = string.Format("Top {0}", limite.ToString());

                if (page > 1)
                {
                    int pageCount = (page - 1) * limite;
                    string subClause = string.Format(@"SELECT TOP {0} [OperationID]
                                                       FROM [dbo].[SYS_OperationLogs] {1} {2}", pageCount.ToString(), whereClause, SQL_SYS_ActionLog_Order);
                    whereClause += string.Format(" AND [OperationID] NOT IN({0})", subClause);
                }
            }
            string mainClause = string.Format(SQL_SYS_ActionLog, topClause);
            string sql = string.Format("{0} {1} {2}", mainClause, whereClause, SQL_SYS_ActionLog_Order);
            DbCommand command = db.GetSqlStringCommand(sql);
            if (dbParams != null)
            {
                command.Parameters.AddRange(dbParams.ToArray());
            }

            DataSet ds = db.ExecuteDataSet(command);
            total = GetRecordCount(countSql, dbParams);

            return ds;
        }

        /// <summary>
        /// 保存操作
        /// </summary>
        /// <param name="operaterID"></param>
        /// <param name="operaterName"></param>
        /// <param name="actionCode"></param>
        /// <param name="actionContent"></param>
        public static void SaveAction(string operaterID, string operaterName, string actionCode, string actionContent)
        {
            Database db = DBHelper.Instance;
            DbCommand cmd = db.GetSqlStringCommand(SQL_SYS_ActionLog_Add);

            #region 造成参数
            DbParameter p_OperationID = cmd.CreateParameter();
            p_OperationID.ParameterName = "OperationID";
            p_OperationID.Value = Guid.NewGuid().ToString();
            cmd.Parameters.Add(p_OperationID);

            DbParameter p_OperationCode = cmd.CreateParameter();
            p_OperationCode.ParameterName = "OperationCode";
            p_OperationCode.Value = string.IsNullOrEmpty(actionCode) ? p_OperationID.Value : actionCode;
            cmd.Parameters.Add(p_OperationCode);

            DbParameter p_OperationContent = cmd.CreateParameter();
            p_OperationContent.ParameterName = "OperationContent";
            p_OperationContent.Value = actionContent;
            cmd.Parameters.Add(p_OperationContent);

            DbParameter p_Operator = cmd.CreateParameter();
            p_Operator.ParameterName = "Operator";
            p_Operator.Value = operaterName;
            cmd.Parameters.Add(p_Operator);

            DbParameter p_OperatorID = cmd.CreateParameter();
            p_OperatorID.ParameterName = "OperatorID";
            p_OperatorID.Value = operaterID;
            cmd.Parameters.Add(p_OperatorID);
            #endregion

            db.ExecuteNonQuery(cmd);
        }
        #endregion
    }
}
